/*
 *  Copyright (C) 2011 felixtheripper <felixtheripper_AT_gmail.com>
 *
 *  This program is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU General Public License
 *  as published by the Free Software Foundation; either version 2
 *  of the License, or (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */

/**
 *
 * @author felixtheripper
 *
 * email: felixtheripper_AT_gmail.com
 * ... please remove "_AT_" from the above string to get the right email address
 *
 */

package org.myorg.ctm.etk.gui.app;


import java.util.Locale;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.UIManager;
import javax.swing.UIManager.LookAndFeelInfo;
import org.myorg.shr.gui.swg.lang.IShrObj;
import org.myorg.ctm.etk.gui.swg.display.frame.*;
import org.myorg.ctm.etk.gui.swg.display.help.*;
import org.myorg.shr.gui.swg.util.logging.FileHandlerShr;
import org.myorg.ctm.etk.gui.swg.util.property.PrpNamingEtk;
import org.myorg.shr.gui.swg.util.property.PrpNamingAbs;

/**
 *
 * 
 */
abstract public class AppAbs implements
	IShrObj
{
    final static private String[] _F_STRS_PROP_SYS_REQUIRED =
    {
        PrpNamingEtk.STR_PRP_APPLI_CACHE,
        PrpNamingEtk.STR_PRP_APPLI_TITLE,
        PrpNamingEtk.STR_PRP_APPLI_VERSION,
        PrpNamingEtk.STR_PRP_NAME_SHORT,
        PrpNamingEtk.STR_PRP_APP_HLP_CTN,
    };

    // waiting for JDK 1.7!
    static
    {
        try
        {
            for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels())
            {
                if ("Nimbus".equals(info.getName()))
                {
                   UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        }
        catch (Exception exc)
        {
            AppAbs._LOGGER_.warning(exc.getMessage());
        }

    }

    static
    {
        // begin: prerequisites, java -D[key]="[value]"
        for (int i=0; i< AppAbs._F_STRS_PROP_SYS_REQUIRED.length; i++)
        {
            if (System.getProperty(AppAbs._F_STRS_PROP_SYS_REQUIRED[i]) == null)
            {
                    System.err.println("missing property: " + AppAbs._F_STRS_PROP_SYS_REQUIRED[i] + ", exiting");
                    System.exit(1);
            }

        }
        // end: prerequisites, java -D[key]="[value]"
    }

    // ----
    // begin: instantiate logger for this class
    final static private Logger _LOGGER_ = Logger.getLogger(AppAbs.class.getName());

    static
    {
            PrpNamingEtk.s_init();
            FileHandlerShr.s_initFileHandler(
                    PrpNamingEtk.STRS_LOGS_PARENT_FOLDERS,
                    PrpNamingEtk.STR_APPLI_VERSION_TRANSFORMED
            );
        AppAbs._LOGGER_.addHandler(FileHandlerShr.s_getInstance());
    }

    // end: instantiate logger for this class
    // ----


   static
   {
       // begin: load libraries (DLL or SO)


        String strKey = PrpNamingEtk.STR_PRP_APP_LIB_CPP;
        String strValue = null;
        try
        {
            strValue = System.getProperty(strKey);

            // modif: nil value allowed
            if (strValue != null)
                System.loadLibrary(strValue);
        }



        catch(Exception exc)
        {
            exc.printStackTrace();
            String strBody = "Exception caught" +
                    "\n" +
                    "failed to load library, strKey=" +
                    strKey +
                    ", strValue=" +
                    strValue;

	    AppAbs._LOGGER_.severe(strBody + "\n exiting");
            //System.err.println("got exception, exiting");
            System.exit(1);
        }        catch(UnsatisfiedLinkError err)
        {
            err.printStackTrace();
            String strBody = "Exception caught" +
                    "\n" +
                    "failed to load library, strKey=" +
                    strKey +
                    ", strValue=" +
                    strValue +
                    ", err.getMessage()" +
                    err.getMessage();

	    AppAbs._LOGGER_.severe(strBody + "\n exiting");
       
            System.exit(1);
        }

        // end: load libraries (DLL or SO)
   }

    @Override
    public boolean init()
    {

        if (! this._frm_.init())
            return false;

        _delayDoHelpBroker_();

        return true;
    }

	public void destroy()
	{
        if (this._frm_ != null){
            this._frm_.destroy();
            this._frm_ = null;
        }

        if (this._vecMyHelpBroker != null){
            for (int i=0; i<this._vecMyHelpBroker.size(); i++)
            {
                EtkHelpBroker mhbCur =
                        (EtkHelpBroker) this._vecMyHelpBroker.elementAt(i);

                if (mhbCur != null){
                    mhbCur.destroy();
                    mhbCur = null;
                }
            }

            this._vecMyHelpBroker.clear();
            this._vecMyHelpBroker = null;
        }
    }

	// ---------
	// protected

	protected FrmPrintableMainAbs _frm_ = null;
	

	protected AppAbs(
			boolean blnSetLAFSwing,  // used to fix up JH's toolbar buttons
			boolean blnInternAllowed // custom help
			)
	{
            AppAbs._LOGGER_.info(System.getProperty(PrpNamingEtk.STR_PRP_APPLI_TITLE) + " now starting ...");

            String strDebug = System.getProperty(PrpNamingEtk.STR_PRP_DEBUG);

            if (strDebug!=null && strDebug.equalsIgnoreCase("true"))
                AppAbs._LOGGER_.info(PrpNamingAbs.USER_HOME + "=" + System.getProperty(PrpNamingAbs.USER_HOME));


            this._blnSetLAFSwing = blnSetLAFSwing;
            this._blnInternAllowed = blnInternAllowed;

            this._vecMyHelpBroker = new Vector<javax.help.HelpBroker>();

	}

	/**
	    a new document/project has been opened, updating JavaHelp's JHEditorPane's StyleSheet
	    vector should contain at least one element: helpStandard
	**/
	protected boolean _updateJavaHelpStyleSheets_()
	{

	    if (this._vecMyHelpBroker == null)
	    {
	    	AppAbs._LOGGER_.severe("this._vecMyHelpBroker == null");
	        return false;
	    }

	    for (int i=0; i<this._vecMyHelpBroker.size(); i++)
	    {
	        EtkHelpBroker mhbCur = null;

	        try
	        {
	            mhbCur = (EtkHelpBroker) this._vecMyHelpBroker.elementAt(i);
	        }

	        catch(ClassCastException excClassCast)
	        {
	            AppAbs._LOGGER_.log(Level.SEVERE, "Exception", excClassCast);
	            return false;
	        }

	        if (! mhbCur.assignStyleSheet())
	        {
	            AppAbs._LOGGER_.severe("failed");
	            return false;
	        }
	    }

	    // ending
	    return true;
	}



    protected javax.help.HelpBroker _doHelpBroker_(String strNameDirHS)
    {
        if (strNameDirHS == null)
        {
                AppAbs._LOGGER_.severe("strNameDirHS == null");
            return null;
        }




        //String strPathRelativeDirHS = new String(strNameDirHS);

        // beg modif for internationalization

        if (this._blnInternAllowed)
        {

            Locale loc = Locale.getDefault();
            String strLocLang = loc.getLanguage();

            if (strLocLang == null)
            {
            	AppAbs._LOGGER_.severe("strLocLang == null");
	            return null;
            }

            // for now, just handling FR
            String[] strsSupported = { "fr" };

            for (int i=0; i<strsSupported.length; i++)
            {
                if (strLocLang.toLowerCase().compareTo(strsSupported[i]) == 0)
                //strPathRelativeDirHS += "_" + strsSupported[i];
                break;
            }


        }

        // end modif for internationalization

        String strHelpsetPathRelativeShort = strNameDirHS; // tempo

        //  TEST
        //MySystem.s_printOutFlagDev(this, strMethod, "TESTING FOR NETBEANS MODULE");
        //if (AppMainAbs.s_isDeployedWithNbm())
          //  strHelpsetPathRelativeShort = "/" + strHelpsetPathRelativeShort;
       // NOT WORKING!


        // ---
        EtkHelpSet hst = null;

        try
        {
	        ClassLoader clr = this.getClass().getClassLoader();
                java.net.URL url = javax.help.HelpSet.findHelpSet(clr, strHelpsetPathRelativeShort);

            if (url == null)
            {
            	AppAbs._LOGGER_.severe("url == null");
                return null;
            }

            hst = new EtkHelpSet(clr, url);

            if (hst == null)
            {
            	AppAbs._LOGGER_.severe("nil hst, strHelpsetPathRelativeShort=" + strHelpsetPathRelativeShort);
            	AppAbs._LOGGER_.severe("... nil hst, url.toString()=" + url.toString());

                return null;
            }
	    }




	    catch (Exception exc)
	    {
	    	AppAbs._LOGGER_.log(Level.SEVERE, "Exception", exc);
	    	return null;
	    }	    catch (ExceptionInInitializerError errExceptionInInitializer)
	    {
	    	AppAbs._LOGGER_.log(Level.SEVERE, "Exception", errExceptionInInitializer.getException());
	        return null;
	    }




	    // MODIF COZ BUG WITH STYLESHEETS IN JAVAHELP
	    /*javax.help.HelpBroker hbr = hst.createHelpBroker();
        if (hbr == null)
        {
            MySystem.s_printOutError(this, strMethod, "nil hbr, strHelpsetPathRelativeShort=" + strHelpsetPathRelativeShort);
	        return null;
        }*/

        //return hbr;


        javax.help.HelpBroker hbrMine = new EtkHelpBroker(
            hst,
            this._blnSetLAFSwing
            );



        if (! ((EtkHelpBroker) hbrMine).init())
        {
        	AppAbs._LOGGER_.severe("failed");
        	return null;
        }

        this._vecMyHelpBroker.addElement(hbrMine);

        //strPathRelativeDirHS = null; // !!
        return hbrMine;
    }

	// -------
	// private

	private boolean _blnSetLAFSwing = false;
	private boolean _blnInternAllowed = false;
	private Vector<javax.help.HelpBroker> _vecMyHelpBroker = null;




	protected javax.help.HelpBroker _hbrHelpContents_ = null;

	protected void _delayDoHelpBroker_()
        {

            // 1)

            javax.swing.SwingUtilities.invokeLater(new Runnable()
            {
            public void run()
            {
            	javax.help.HelpBroker hbrHelpGettingStarted =
            		_doHelpBroker_(System.getProperty(
                        PrpNamingEtk.STR_PRP_APP_GETTING_STARTED));

            if (hbrHelpGettingStarted == null)
            {
            	AppAbs._LOGGER_.severe("hbrHelpGettingStarted == null, exiting");
            	System.exit(1);
            }

            else
            {
            	_frm_.setEnabledHelpGettingStarted(hbrHelpGettingStarted); // menuBar's menuItem

            }
        }
      });



            // 2)


            javax.swing.SwingUtilities.invokeLater(new Runnable()
            {
            public void run()
            {
                String strPathRelHelpsetContents = System.getProperty(PrpNamingEtk.STR_PRP_APP_HLP_CTN);

                if (strPathRelHelpsetContents == null)
                {
                    AppAbs._LOGGER_.severe("strPathRelHelpset == null, exiting");
                    System.exit(1);
                }

            	_hbrHelpContents_ = _doHelpBroker_(strPathRelHelpsetContents);

            if (_hbrHelpContents_ == null)
            {
            	AppAbs._LOGGER_.severe("_hbrHelpContents_ == null, exiting, strPathRelHelpsetContents=" + strPathRelHelpsetContents);
            	System.exit(1);
            }

            else
            {
            	_frm_.setEnabledHelpKey(_hbrHelpContents_); // F1 key
            	_frm_.setEnabledHelpSourceAndTrack(_hbrHelpContents_); // menuBar's menuItem & toolbar's iconButtons
            	_frm_.setEnabledHelpOnContext();

            	if (! EtkCSH.s_checkAndDumpCmp2ID(_hbrHelpContents_.getHelpSet()))
            	{
            		AppAbs._LOGGER_.severe("failed to check and dump Cmp2ID, exiting");
                	System.exit(1);
            	}

            }
        }
      });
    }
}
